#include "mempool.h"
#include <gtest/gtest.h>
#include <unordered_set>

class MemoryPoolTest : public ::testing::Test {
protected:
    MemoryPool* pool;
    const size_t block_size = 64;
    const size_t block_count = 10;

    void SetUp() override {
        pool = new MemoryPool(block_size, block_count);
    }

    void TearDown() override {
        delete pool;
    }
};

// 测试全部分配成功
TEST_F(MemoryPoolTest, AllocateAllBlocks) {
    std::unordered_set<void*> allocated;
    for (size_t i = 0; i < block_count; ++i) {
        void* ptr = pool->allocate();
        EXPECT_NE(ptr, nullptr);
        EXPECT_TRUE(allocated.find(ptr) == allocated.end()); // 不重复
        allocated.insert(ptr);
    }

    // 分配超出应返回 nullptr
    EXPECT_EQ(pool->allocate(), nullptr);
}

// 测试回收后再次分配成功
TEST_F(MemoryPoolTest, AllocateAfterFree) {
    std::vector<void*> blocks;
    for (size_t i = 0; i < block_count; ++i) {
        void* ptr = pool->allocate();
        EXPECT_NE(ptr, nullptr);
        blocks.push_back(ptr);
    }

    // 全部释放
    for (void* ptr : blocks) {
        pool->deallocate(ptr);
    }

    // 应该能重新分配
    for (size_t i = 0; i < block_count; ++i) {
        void* ptr = pool->allocate();
        EXPECT_NE(ptr, nullptr);
    }
}

// 测试空指针释放不崩溃
TEST_F(MemoryPoolTest, DeallocateNull) {
    EXPECT_NO_THROW(pool->deallocate(nullptr));
}

// 多次重复分配释放，不应崩溃
TEST_F(MemoryPoolTest, MultipleReuse) {
    for (int round = 0; round < 1000; ++round) {
        std::vector<void*> blocks;
        for (size_t i = 0; i < block_count; ++i) {
            void* ptr = pool->allocate();
            ASSERT_NE(ptr, nullptr);
            blocks.push_back(ptr);
        }

        for (void* ptr : blocks) {
            pool->deallocate(ptr);
        }
    }
}
